package pl.veneo.wigprofit.view.elements {
	import pl.veneo.wigprofit.ctrl.events.ChartResizeEvent;
	import pl.veneo.wigprofit.model.Configuration;
	import pl.veneo.wigprofit.model.PeriodData;
	import pl.veneo.wigprofit.tools.TimeSpan;
	import pl.veneo.wigprofit.view.CursorManager;

	import flash.display.Sprite;
	import flash.events.MouseEvent;
	import flash.text.TextField;
	import flash.text.TextFieldAutoSize;
	import flash.text.TextFormat;
	import flash.text.TextFormatAlign;

	/**
	 * @author Tomasz Swierszcz, fiodorkrk@gmail.com
	 */
	public class ChartArrow extends Sprite {
		private var _width : Number;
		private var _height : Number;
		private var _arrow : ArrowElement;
		private var _area : Sprite;
		private var _mask : Sprite;
		private var _info : TextField;
		private var _period : PeriodData;
		private var _box : Sprite;

		public function ChartArrow(width : Number, height : Number) {
			_height = height;
			_width = width;

			_arrow = addChild(new ArrowElement(width, height)) as ArrowElement;

			_mask = addChild(new Sprite()) as Sprite;
			_mask.graphics.beginFill(0x00FF00, 0);
			_mask.graphics.drawRect(0, 0, width, height);
			_mask.graphics.endFill();

			_arrow.mask = _mask;

			_box = addChild(new Sprite()) as Sprite;

			_area = addChild(new Sprite()) as Sprite;
			_area.graphics.beginFill(0xFF0000, 0);
			_area.graphics.drawRect(-1, 0, width + 1, height);
			_area.graphics.endFill();

			_area.addEventListener(MouseEvent.MOUSE_OVER, showArrow);
			_area.addEventListener(MouseEvent.MOUSE_OUT, hideArrow);
			_area.addEventListener(MouseEvent.MOUSE_DOWN, startDraw);

			_info = addChild(new TextField()) as TextField;
			_info.border = true;
			_info.defaultTextFormat = getStyleForIndex();
			_info.borderColor = Configuration.getInstance().lightColor;
			_info.background = true;
			_info.multiline = true;
			_info.backgroundColor = 0xFFFFFF;
			_info.selectable = false;
			_info.mouseEnabled = false;
			_info.autoSize = TextFieldAutoSize.LEFT;

			_arrow.visible = false;
			_info.visible = false;
		}

		private function startDraw(event : MouseEvent) : void {
			_box.graphics.clear();
			_box.x = this.mouseX;
			_box.y = this.mouseY;
			_area.addEventListener(MouseEvent.MOUSE_MOVE, updateDraw);
			_area.addEventListener(MouseEvent.MOUSE_UP, endDraw);
		}

		private function endDraw(event : MouseEvent) : void {
			var minX : Number = _box.x < this.mouseX ? _box.x : this.mouseX;
			var maxX : Number = _box.x > this.mouseX ? _box.x : this.mouseX;

			var dateBeg: Date = getDateForPositionX(minX);
			dateBeg.hours = 0;
			dateBeg.minutes = 0;
			dateBeg.seconds = 0;
			dateBeg.milliseconds = 0;
			var dateEnd: Date = getDateForPositionX(maxX);
			dateEnd.hours = 0;
			dateEnd.minutes = 0;
			dateEnd.seconds = 0;
			dateEnd.milliseconds = 0;
			
			var span: TimeSpan = TimeSpan.fromDates(dateBeg, dateEnd);
			if(span.days<10){
				var startMs : Number = dateBeg.valueOf();
				dateBeg.setTime(startMs - (2 * TimeSpan.MILLISECONDS_IN_DAY));
				dateEnd.setTime(startMs + (8 * TimeSpan.MILLISECONDS_IN_DAY));
			}
			
			dispatchEvent(new ChartResizeEvent(ChartResizeEvent.ON_CHART_RESIZE, dateBeg, dateEnd, true));

			_box.graphics.clear();
			_area.removeEventListener(MouseEvent.MOUSE_MOVE, updateDraw);
			_area.removeEventListener(MouseEvent.MOUSE_UP, endDraw);
		}

		private function getDateForPositionX(posX : Number) : Date {
			var startDay : Number = _period.startDay.valueOf();
			var days : Number = Math.floor(posX / _width * _period.days);
			var miliseconds : Number = days * TimeSpan.MILLISECONDS_IN_DAY;
			var date : Date = new Date();
			date.setTime(startDay + miliseconds);
			return date;
		}

		private function updateDraw(event : MouseEvent) : void {
			_box.graphics.clear();
			_box.graphics.lineStyle(0, 0, 0.5);
			_box.graphics.drawRect(0, 0, this.mouseX - _box.x, this.mouseY - _box.y);
		}

		public function draw(period : PeriodData) : void {
			_period = period;
		}

		private function hideArrow(event : MouseEvent) : void {
			CursorManager.getInstance().switchTo(CursorManager.NORMAL);
			_arrow.visible = false;
			_info.visible = false;
			_area.removeEventListener(MouseEvent.MOUSE_MOVE, updateArrow);
		}

		private function showArrow(event : MouseEvent) : void {
			CursorManager.getInstance().switchTo(CursorManager.ARROW);
			_arrow.visible = true;
			_info.visible = true;
			_area.addEventListener(MouseEvent.MOUSE_MOVE, updateArrow);
		}

		private function updateArrow(event : MouseEvent) : void {
			_arrow.x = this.mouseX;
			_arrow.y = this.mouseY;

			var min : Number = _period.minIndex;
			var max : Number = _period.maxIndex;

			var overscale : Number = (max - min) * 0.05;
			min -= overscale;
			max += overscale;

			var step : Number = ( max - min ) / _height;
			var indexv : Number = max - (this.mouseY * step);

			var color1 : String = "#" + uint2hex(Configuration.getInstance().indexColor);
			var color2 : String = "#" + uint2hex(Configuration.getInstance().percentColor);
			var color3 : String = "#" + uint2hex(Configuration.getInstance().lightColor);
			var text : String = "<font color='" + color1 + "'>" + formatIndexValue(indexv) + "</font><br>";
			text += "<font color='" + color2 + "'>" + String(Math.round(100 - (100 * this.mouseY / _height))) + "%</font><br>";
			text += "<font color='" + color3 + "'>" + getDateForPosition() + "</font><br>";

			_info.htmlText = text;
			if (this.mouseX > _info.width)
				_info.x = this.mouseX - 4 - _info.width;
			else
				_info.x = this.mouseX + 4;

			if (this.mouseY > _info.width)
				_info.y = this.mouseY - 4 - _info.height;
			else
				_info.y = this.mouseY + 4;
		}

		private function getDateForPosition() : String {
			var startDay : Number = _period.startDay.valueOf();
			var days : Number = Math.floor(this.mouseX / _width * _period.days);
			var miliseconds : Number = days * TimeSpan.MILLISECONDS_IN_DAY;
			var date : Date = new Date();
			date.setTime(startDay + miliseconds);
			return String(date.date) + "-" + String(date.month + 1) + "-" + String(date.fullYear);
		}

		private function formatIndexValue(value : Number) : String {
			var before : String = String(value);
			var out : String = before.split('.')[0];
			var end : String = before.split('.')[1];
			end = end.length == 1 ? "0" + end : end;
			end = end.length > 2 ? end.substr(0, 2) : end;
			return out + '.' + end;
		}

		private function uint2hex(dec : uint) : String {
			var digits : String = "0123456789ABCDEF";
			var hex : String = '';
			while (dec > 0) {
				var next : uint = dec & 0xF;
				dec >>= 4;
				hex = digits.charAt(next) + hex;
			}
			if (hex.length == 0) hex = '0';
			return hex;
		}

		private function getStyleForIndex() : TextFormat {
			var tf : TextFormat = new TextFormat();
			tf.size = 9;
			tf.align = TextFormatAlign.RIGHT;
			tf.font = "Tahoma";
			tf.color = Configuration.getInstance().lightColor;
			return tf;
		}
	}
}
